home *** CD-ROM | disk | FTP | other *** search
/ Aminet 23 / Aminet 23 (1998)(GTI - Schatztruhe)[!][Feb 1998].iso / Aminet / misc / emu / amiSPIMsrc.lha / mem.c < prev    next >
C/C++ Source or Header  |  1994-01-17  |  20KB  |  795 lines

  1. /* SPIM S20 MIPS simulator.
  2.    Code to create, maintain and access memory.
  3.    Copyright (C) 1990-1994 by James Larus (larus@cs.wisc.edu).
  4.    ALL RIGHTS RESERVED.
  5.  
  6.    SPIM is distributed under the following conditions:
  7.  
  8.      You may make copies of SPIM for your own use and modify those copies.
  9.  
  10.      All copies of SPIM must retain my name and copyright notice.
  11.  
  12.      You may not sell SPIM or distributed SPIM in conjunction with a
  13.      commerical product or service without the expressed written consent of
  14.      James Larus.
  15.  
  16.    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19.    PURPOSE. */
  20.  
  21.  
  22. /* $Header: /home/primost/larus/Software/SPIM/RCS/mem.c,v 3.26 1994/01/18 03:21:45 larus Exp larus $
  23. */
  24.  
  25.  
  26. #include "spim.h"
  27. #include "spim-utils.h"
  28. #include "inst.h"
  29. #include "mem.h"
  30. #include "reg.h"
  31.  
  32. #ifdef CL_SPIM
  33. #include "cl-mem.h"
  34. #endif
  35.  
  36.  
  37. /* Exported Variables: */
  38.  
  39. reg_word R[32];
  40. reg_word HI, LO;
  41. int HI_present, LO_present;
  42. mem_addr PC, nPC;
  43. double *FPR;            /* Dynamically allocate so overlay */
  44. float *FGR;            /* is possible */
  45. int *FWR;            /* is possible */
  46. int FP_reg_present;        /* Presence bits for FP registers */
  47. int FP_reg_poison;        /* Poison bits for FP registers */
  48. int FP_spec_load;        /* Is register waiting for a speculative ld */
  49. reg_word CpCond[4], CCR[4][32], CPR[4][32];
  50.  
  51. instruction **text_seg;
  52. int text_modified;        /* Non-zero means text segment was written */
  53. mem_addr text_top;
  54. mem_word *data_seg;
  55. int data_modified;        /* Non-zero means a data segment was written */
  56. short *data_seg_h;        /* Points to same vector as DATA_SEG */
  57. BYTE_TYPE *data_seg_b;        /* Ditto */
  58. mem_addr data_top;
  59. mem_addr gp_midpoint;        /* Middle of $gp area */
  60. mem_word *stack_seg;
  61. short *stack_seg_h;        /* Points to same vector as STACK_SEG */
  62. BYTE_TYPE *stack_seg_b;        /* Ditto */
  63. mem_addr stack_bot;
  64. instruction **k_text_seg;
  65. mem_addr k_text_top;
  66. mem_word *k_data_seg;
  67. short *k_data_seg_h;
  68. mem_addr k_data_top;
  69.  
  70.  
  71. /* Local functions: */
  72.  
  73. #ifdef __STDC__
  74. static void free_instructions (register instruction **inst, int n);
  75. static mem_word read_memory_mapped_IO (mem_addr addr);
  76. static void write_memory_mapped_IO (mem_addr addr, mem_word value);
  77. #else
  78. static void free_instructions ();
  79. static mem_word read_memory_mapped_IO ();
  80. static void write_memory_mapped_IO ();
  81. #endif
  82.  
  83.  
  84. /* Local variables: */
  85.  
  86. static long data_size_limit, stack_size_limit, k_data_size_limit;
  87.  
  88.  
  89.  
  90. /* Memory is allocated in five chunks:
  91.     text, data, stack, kernel text, and kernel data.
  92.  
  93.    The arrays are independent and have different semantics.
  94.  
  95.    text is allocated from 0x400000 up and only contains INSTRUCTIONs.
  96.    It does not expand.
  97.  
  98.    data is allocated from 0x10000000 up.  It can be extended by the
  99.    SBRK system call.  Programs can only read and write this segment.
  100.  
  101.    stack grows from 0x7fffefff down.  It is automatically extended.
  102.    Programs can only read and write this segment.
  103.  
  104.    k_text is like text, except its is allocated from 0x80000000 up.
  105.  
  106.    k_data is like data, but is allocated from 0x90000000 up.
  107.  
  108.    Both kernel text and kernel data can only be accessed in kernel mode.
  109. */
  110.  
  111.  
  112. #ifdef __STDC__
  113. void
  114. make_memory (long int text_size, long int data_size, long int data_limit,
  115.     long int stack_size, long int stack_limit, long int k_text_size,
  116.     long int k_data_size, long int k_data_limit)
  117. #else
  118. void
  119. make_memory (text_size,
  120.          data_size, data_limit,
  121.          stack_size, stack_limit,
  122.          k_text_size,
  123.          k_data_size, k_data_limit)
  124.      long text_size, data_size, data_limit, stack_size, stack_limit,
  125.        k_text_size, k_data_size, k_data_limit;
  126. #endif
  127. {
  128.   if (data_size <= 65536)
  129.     data_size = 65536;
  130.   if (text_seg == NULL)
  131.     text_seg = (instruction **)
  132.       xmalloc (sizeof (instruction *) * text_size / BYTES_PER_WORD);
  133.   else
  134.     {
  135.       free_instructions (text_seg, (text_top - TEXT_BOT) / BYTES_PER_WORD);
  136.       text_seg = (instruction **) realloc (text_seg, text_size);
  137.     }
  138.   bzero (text_seg, sizeof (instruction *) * text_size / BYTES_PER_WORD);
  139.   text_top = TEXT_BOT + text_size;
  140.  
  141.   if (data_seg == NULL)
  142.     data_seg =
  143.       (mem_word *) xmalloc (sizeof (mem_word) * data_size / BYTES_PER_WORD);
  144.   bzero (data_seg, sizeof (instruction *) * data_size / BYTES_PER_WORD);
  145.   data_seg_b = (BYTE_TYPE *) data_seg;
  146.   data_seg_h = (short *) data_seg;
  147.   data_top = DATA_BOT + data_size;
  148.   data_size_limit = data_limit;
  149.  
  150.   if (stack_seg == NULL)
  151.     stack_seg =
  152.       (mem_word *) xmalloc (sizeof (mem_word) * stack_size / BYTES_PER_WORD);
  153.   bzero (stack_seg, sizeof (instruction *) * stack_size / BYTES_PER_WORD);
  154.   stack_seg_b = (BYTE_TYPE *) stack_seg;
  155.   stack_seg_h = (short *) stack_seg;
  156.   stack_bot = STACK_TOP - stack_size;
  157.   stack_size_limit = stack_limit;
  158.  
  159.   if (k_text_seg == NULL)
  160.     k_text_seg = (instruction **)
  161.       xmalloc (sizeof (instruction *) * k_text_size / BYTES_PER_WORD);
  162.   else
  163.     free_instructions (k_text_seg, (k_text_top - K_TEXT_BOT) / BYTES_PER_WORD);
  164.   bzero (k_text_seg, sizeof (instruction *) * k_text_size / BYTES_PER_WORD);
  165.   k_text_top = K_TEXT_BOT + k_text_size;
  166.  
  167.   if (k_data_seg == NULL)
  168.     k_data_seg =
  169.       (mem_word *) xmalloc (sizeof (mem_word) * k_data_size / BYTES_PER_WORD);
  170.   bzero (k_data_seg, sizeof (instruction *) * k_data_size / BYTES_PER_WORD);
  171.   k_data_seg_b = (BYTE_TYPE *) k_data_seg;
  172.   k_data_seg_h = (short *) k_data_seg;
  173.   k_data_top = K_DATA_BOT + k_data_size;
  174.   k_data_size_limit = k_data_limit;
  175.  
  176.   text_modified = 0;
  177.   data_modified = 0;
  178. }
  179.  
  180.  
  181. /* Free the storage used by the old instructions in memory. */
  182.  
  183. #ifdef __STDC__
  184. static void
  185. free_instructions (register instruction **inst, int n)
  186. #else
  187. static void
  188. free_instructions (inst, n)
  189.      register instruction **inst;
  190.      int n;
  191. #endif
  192. {
  193.   for ( ; n > 0; n --, inst ++)
  194.     if (*inst)
  195.       free_inst (*inst);
  196. }
  197.  
  198.  
  199. /* Expand the data segment by adding N bytes. */
  200.  
  201. #ifdef __STDC__
  202. void
  203. expand_data (long int addl_bytes)
  204. #else
  205. void
  206. expand_data (addl_bytes)
  207.      long addl_bytes;
  208. #endif
  209. {
  210.   long old_size = data_top - DATA_BOT;
  211.   long new_size = old_size + addl_bytes;
  212.   register mem_word *p;
  213.  
  214.   if (addl_bytes < 0 || (source_file && new_size > data_size_limit))
  215.     {
  216.       error ("Can't expand data segment by %d bytes to %d bytes\n",
  217.          addl_bytes, new_size);
  218.       run_error ("Use -ldata # with # > %d\n", new_size);
  219.     }
  220.   data_seg = (mem_word *) realloc (data_seg, new_size);
  221.   if (data_seg == NULL)
  222.     fatal_error ("realloc failed in expand_data\n");
  223.   data_seg_b = (BYTE_TYPE *) data_seg;
  224.   data_seg_h = (short *) data_seg;
  225.   for (p = data_seg + old_size / BYTES_PER_WORD;
  226.        p < data_seg + new_size / BYTES_PER_WORD; )
  227.     *p ++ = 0;
  228.   data_top += addl_bytes;
  229. }
  230.  
  231.  
  232. /* Expand the stack segment by adding N bytes.  Can't use REALLOC
  233.    since it copies from bottom of memory blocks and stack grows down from
  234.    top of its block. */
  235.  
  236. #ifdef __STDC__
  237. void
  238. expand_stack (long int addl_bytes)
  239. #else
  240. void
  241. expand_stack (addl_bytes)
  242.      long addl_bytes;
  243. #endif
  244. {
  245.   long old_size = STACK_TOP - stack_bot;
  246.   long new_size = old_size + MAX (addl_bytes, old_size);
  247.   mem_word *new_seg;
  248.   register mem_word *po, *pn;
  249.  
  250.   if (addl_bytes < 0 || (source_file && new_size > stack_size_limit))
  251.     {
  252.       error ("Can't expand stack segment by %d bytes to %d bytes\n",
  253.          addl_bytes, new_size);
  254.       run_error ("Use -lstack # with # > %d\n", new_size);
  255.     }
  256.  
  257.   new_seg = (mem_word *) xmalloc (new_size);
  258.   po = stack_seg + (old_size / BYTES_PER_WORD - 1);
  259.   pn = new_seg + (new_size / BYTES_PER_WORD - 1);
  260.  
  261.   for ( ; po >= stack_seg ; ) *pn -- = *po --;
  262.   for ( ; pn >= new_seg ; ) *pn -- = 0;
  263.  
  264.   free (stack_seg);
  265.   stack_seg = new_seg;
  266.   stack_seg_b = (BYTE_TYPE *) stack_seg;
  267.   stack_seg_h = (short *) stack_seg;
  268.   stack_bot -= (new_size - old_size);
  269. }
  270.  
  271.  
  272. /* Expand the kernel data segment by adding N bytes. */
  273.  
  274. #ifdef __STDC__
  275. void
  276. expand_k_data (long int addl_bytes)
  277. #else
  278. void
  279. expand_k_data (addl_bytes)
  280.      long addl_bytes;
  281. #endif
  282. {
  283.   long old_size = k_data_top - K_DATA_BOT;
  284.   long new_size = old_size + addl_bytes;
  285.   register mem_word *p;
  286.  
  287.   if (addl_bytes < 0 || (source_file && new_size > k_data_size_limit))
  288.     {
  289.       error ("Can't expand kernel data segment by %d bytes to %d bytes\n",
  290.          addl_bytes, new_size);
  291.       run_error ("Use -lkdata # with # > %d\n", new_size);
  292.     }
  293.   k_data_seg = (mem_word *) realloc (k_data_seg, new_size);
  294.   if (k_data_seg == NULL)
  295.     fatal_error ("realloc failed in expand_k_data\n");
  296.   k_data_seg_b = (BYTE_TYPE *) k_data_seg;
  297.   k_data_seg_h = (short *) k_data_seg;
  298.   for (p = k_data_seg + old_size / BYTES_PER_WORD;
  299.        p < k_data_seg + new_size / BYTES_PER_WORD; )
  300.     *p ++ = 0;
  301.   k_data_top += addl_bytes;
  302. }
  303.  
  304.  
  305.  
  306. /* Handle the infrequent and erroneous cases in the memory access macros. */
  307.  
  308. #ifdef __STDC__
  309. instruction *
  310. bad_text_read (mem_addr addr)
  311. #else
  312. instruction *
  313. bad_text_read (addr)
  314.      mem_addr addr;
  315. #endif
  316. {
  317.   mem_word bits;
  318.  
  319.   READ_MEM_WORD (bits, addr);
  320.   return (inst_decode (bits));
  321. }
  322.  
  323.  
  324. #ifdef __STDC__
  325. void
  326. bad_text_write (mem_addr addr, instruction *inst)
  327. #else
  328. void
  329. bad_text_write (addr, inst)
  330.      mem_addr addr;
  331.      instruction *inst;
  332. #endif
  333. {
  334.   SET_MEM_WORD (addr, ENCODING (inst));
  335. }
  336.  
  337.  
  338. #ifdef __STDC__
  339. mem_word
  340. bad_mem_read (mem_addr addr, int mask, mem_word *dest)
  341. #else
  342. mem_word
  343. bad_mem_read (addr, mask, dest)
  344.      mem_addr addr;
  345.      int mask;
  346.      mem_word *dest;
  347. #endif
  348. {
  349.   mem_word tmp;
  350.  
  351.   if (addr & mask)
  352.     RAISE_EXCEPTION (ADDRL_EXCPT, BadVAddr = addr)
  353.   else if (addr >= TEXT_BOT && addr < text_top)
  354.     switch (mask)
  355.       {
  356.       case 0x0:
  357.     tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
  358. #ifdef BIGENDIAN
  359.     tmp = tmp >> (8 * (3 - (addr & 0x3)));
  360. #else
  361.     tmp = tmp >> (8 * (addr & 0x3));
  362. #endif
  363.     return (0xff & tmp);
  364.  
  365.       case 0x1:
  366.     tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
  367. #ifdef BIGENDIAN
  368.     tmp = tmp >> (8 * (2 - (addr & 0x2)));
  369. #else
  370.     tmp = tmp >> (8 * (addr & 0x2));
  371. #endif
  372.     return (0xffff & tmp);
  373.  
  374.       case 0x3:
  375.     return (ENCODING (text_seg [(addr - TEXT_BOT) >> 2]));
  376.  
  377.       default:
  378.     run_error ("Bad mask (0x%x) in bad_mem_read\n", mask);
  379.       }
  380.   else if (addr > data_top
  381.        && addr < stack_bot
  382.        /* If more than 16 MB below stack, probably is bad data ref */
  383.        && addr > stack_bot - 16*1000*K)
  384.     {
  385.       /* Grow stack segment */
  386.       expand_stack (stack_bot - addr + 4);
  387.       *dest = 0;        /* Newly allocated memory */
  388.       return (0);
  389.     }
  390.   else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP)
  391.     return (read_memory_mapped_IO (addr));
  392.   else
  393.     /* Address out of range */
  394.     RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
  395.   return (0);
  396. }
  397.  
  398.  
  399. #ifdef __STDC__
  400. void
  401. bad_mem_write (mem_addr addr, mem_word value, int mask)
  402. #else
  403. void
  404. bad_mem_write (addr, value, mask)
  405.      mem_addr addr;
  406.      mem_word value;
  407.      int mask;
  408. #endif
  409. {
  410.   mem_word tmp;
  411.  
  412.   if (addr & mask)
  413.     /* Unaligned address fault */
  414.     RAISE_EXCEPTION (ADDRS_EXCPT, BadVAddr = addr)
  415.   else if (addr >= TEXT_BOT && addr < text_top)
  416.     switch (mask)
  417.       {
  418.       case 0x0:
  419.     tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
  420. #ifdef BIGENDIAN
  421.     tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3)))))
  422.            | (value & 0xff) << (8 * (3 - (addr & 0x3))));
  423. #else
  424.     tmp = ((tmp & ~(0xff << (8 * (addr & 0x3))))
  425.            | (value & 0xff) << (8 * (addr & 0x3)));
  426. #endif
  427.     text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);
  428.     break;
  429.  
  430.       case 0x1:
  431.     tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
  432. #ifdef BIGENDIAN
  433.     tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2)))))
  434.            | (value & 0xffff) << (8 * (2 - (addr & 0x2))));
  435. #else
  436.     tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2))))
  437.            | (value & 0xffff) << (8 * (addr & 0x2)));
  438. #endif
  439.     text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);
  440.     break;
  441.  
  442.       case 0x3:
  443.     text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (value);
  444.     break;
  445.  
  446.       default:
  447.     run_error ("Bad mask (0x%x) in bad_mem_read\n", mask);
  448.       }
  449.   else if (addr > data_top
  450.        && addr < stack_bot
  451.        /* If more than 16 MB below stack, probably is bad data ref */
  452.        && addr > stack_bot - 16*1000*K)
  453.     {
  454.       /* Grow stack segment */
  455.       expand_stack (stack_bot - addr + 4);
  456.       if (addr >= stack_bot)
  457.     {
  458.       if (mask == 0)
  459.         stack_seg_b [addr - stack_bot] = value;
  460.       else if (mask == 1)
  461.         stack_seg_h [(addr - stack_bot) > 1] = value;
  462.       else
  463.         stack_seg [(addr - stack_bot) >> 2] = value;
  464.     }
  465.       else
  466.     RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
  467.     }
  468.   else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP)
  469.     write_memory_mapped_IO (addr, value);
  470.   else
  471.     /* Address out of range */
  472.     RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
  473. }
  474.  
  475.  
  476.  
  477. /* Handle infrequent and erroneous cases in cycle-level SPIM memory
  478.    access macros. */
  479.  
  480. #ifdef CL_SPIM
  481. #ifdef __STDC__
  482. instruction *
  483. cl_bad_text_read (mem_addr addr, int *excpt)
  484. #else
  485. instruction *
  486. cl_bad_text_read (addr, excpt)
  487.      mem_addr addr;
  488.      int *excpt;
  489. #endif
  490. {
  491.   mem_word bits;
  492.  
  493.   BASIC_READ_MEM_WORD (bits, addr, excpt);
  494.   return (inst_decode (bits));
  495. }
  496.  
  497.  
  498. #ifdef __STDC__
  499. void
  500. cl_bad_text_write (mem_addr addr, instruction *inst, int *excpt)
  501. #else
  502. void
  503. cl_bad_text_write (addr, inst, excpt)
  504.      mem_addr addr;
  505.      instruction *inst;
  506.      int *excpt;
  507. #endif
  508. {
  509.   SET_MEM_WORD (addr, ENCODING (inst));
  510. }
  511.  
  512.  
  513. #ifdef __STDC__
  514. mem_word
  515. cl_bad_mem_read (mem_addr addr, int mask, mem_word *dest, int *excpt)
  516. #else
  517. mem_word
  518. cl_bad_mem_read (addr, mask, dest, excpt)
  519.      mem_addr addr;
  520.      int mask;
  521.      mem_word *dest;
  522.      int *excpt;
  523. #endif
  524. {
  525.   if (addr & mask){
  526.     CL_RAISE_EXCEPTION (ADDRL_EXCPT, 0, *excpt);
  527.     BadVAddr = addr;
  528.   }
  529.   else if (addr >= TEXT_BOT && addr < text_top)
  530.     {
  531.       if (mask != 0x3)
  532.     run_error ("SPIM restriction: Can only read text segment by words\n");
  533.       else
  534.     return (ENCODING (text_seg [(addr - TEXT_BOT) >> 2]));
  535.     }
  536.   else if (addr > data_top
  537.        && addr < stack_bot
  538.        /* If more than 16 MB below stack, probably is bad data ref */
  539.        && addr > stack_bot - 16*1000*K)
  540.     {
  541.       /* Grow stack segment */
  542.       expand_stack (stack_bot - addr + 4);
  543.       *dest = 0;                 /* Newly allocated memory */
  544.     }
  545.   else {
  546.     /* Address out of range */
  547.     CL_RAISE_EXCEPTION (DBUS_EXCPT, 0, *excpt);
  548.     BadVAddr = addr;
  549.   }
  550.   return (0);
  551.  
  552. }
  553.  
  554.  
  555. #ifdef __STDC__
  556. void
  557. cl_bad_mem_write (mem_addr addr, mem_word value, int mask, int *excpt)
  558. #else
  559. void
  560. cl_bad_mem_write (addr, value, mask, excpt)
  561.      mem_addr addr;
  562.      mem_word value;
  563.      int mask;
  564.      int *excpt;
  565. #endif
  566. {
  567.   if (addr & mask) {
  568.     /* Unaligned address fault */
  569.     CL_RAISE_EXCEPTION (ADDRS_EXCPT, 0, *excpt);
  570.     BadVAddr = addr;
  571.   }
  572.   else if (addr >= TEXT_BOT && addr < text_top)
  573.     {
  574.       if (mask != 0x3)
  575.     run_error ("SPIM restriction: Can only write text segment by words\n");
  576.       else
  577.     text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (value);
  578.     }
  579.   else if (addr > data_top
  580.        && addr < stack_bot
  581.        /* If more than 16 MB below stack, probably is bad data ref */
  582.        && addr > stack_bot - 16*1000*K)
  583.     {
  584.       /* Grow stack segment */
  585.       expand_stack (stack_bot - addr + 4);
  586.       if (addr >= stack_bot)
  587.     {
  588.       if (mask == 0)
  589.         stack_seg_b [addr - stack_bot] = value;
  590.       else if (mask == 1)
  591.         stack_seg_h [addr - stack_bot] = value;
  592.       else
  593.         stack_seg [addr - stack_bot] = value;
  594.     }
  595.       else {
  596.     CL_RAISE_EXCEPTION (DBUS_EXCPT, 0, *excpt);
  597.         BadVAddr = addr;
  598.       }
  599.     }
  600.   else {
  601.     /* Address out of range */
  602.     CL_RAISE_EXCEPTION (DBUS_EXCPT, 0, *excpt);
  603.     BadVAddr = addr;
  604.     }
  605. }
  606. #endif
  607.  
  608.  
  609.  
  610. /* Memory-mapped IO routines: */
  611.  
  612. static long recv_control, recv_buffer, recv_buffer_filled;
  613. static long trans_control, trans_buffer, trans_buffer_filled;
  614.  
  615.  
  616. /* Every IO_INTERVAL time steps, check if input is available and output
  617.    is possible.  If so, update the control registers and buffers. */
  618.  
  619. #ifdef __STDC__
  620. void
  621. check_memory_mapped_IO (void)
  622. #else
  623. void
  624. check_memory_mapped_IO ()
  625. #endif
  626. {
  627.   static long mm_io_initialized = 0;
  628.  
  629.   if (!mm_io_initialized)
  630.     {
  631.       recv_control = RECV_READY;
  632.       trans_control = TRANS_READY;
  633.       mm_io_initialized = 1;
  634.     }
  635.  
  636.   if (console_input_available ())
  637.     {
  638.       recv_buffer_filled -= IO_INTERVAL;
  639.       if (recv_buffer_filled <= 0)
  640.     {
  641.       recv_buffer = get_console_char ();
  642.       recv_control |= RECV_READY;
  643.       recv_buffer_filled = RECV_LATENCY;
  644.       if ((recv_control & RECV_INT_ENABLE)
  645.           && INTERRUPTS_ON
  646.           && (Status_Reg & RECV_INT_MASK))
  647.         RAISE_EXCEPTION (INT_EXCPT, Cause |= RECV_INT_MASK);
  648.     }
  649.     }
  650.   else if (recv_buffer_filled <= 0)
  651.     recv_control &= ~RECV_READY;
  652.  
  653.   if (trans_buffer_filled > 0)
  654.     {
  655.       trans_buffer_filled -= IO_INTERVAL;
  656.       if (trans_buffer_filled <= 0)
  657.     {
  658.       put_console_char (trans_buffer);
  659.       trans_control |= TRANS_READY;
  660.       trans_buffer_filled = 0;
  661.       if ((trans_control & TRANS_INT_ENABLE)
  662.           && INTERRUPTS_ON
  663.           && (Status_Reg & TRANS_INT_MASK))
  664.         RAISE_EXCEPTION (INT_EXCPT, Cause |= TRANS_INT_MASK)
  665.     }
  666.     }
  667. }
  668.  
  669.  
  670. /* Invoked on a write in the memory-mapped IO area. */
  671.  
  672. #ifdef __STDC__
  673. static void
  674. write_memory_mapped_IO (mem_addr addr, mem_word value)
  675. #else
  676. static void
  677. write_memory_mapped_IO (addr, value)
  678.      mem_addr addr;
  679.      mem_word value;
  680. #endif
  681. {
  682.   switch (addr)
  683.     {
  684.     case TRANS_CTRL_ADDR:
  685.       trans_control = ((trans_control & ~TRANS_INT_ENABLE)
  686.                | (value & TRANS_INT_ENABLE));
  687.  
  688.       if ((trans_control & TRANS_READY)
  689.       && (trans_control & TRANS_INT_ENABLE)
  690.       && INTERRUPTS_ON
  691.       && (Status_Reg & TRANS_INT_MASK))
  692.     /* Raise an interrupt immediately on enabling a ready xmitter */
  693.     RAISE_EXCEPTION (INT_EXCPT, Cause |= TRANS_INT_MASK)
  694.       break;
  695.  
  696.     case TRANS_BUFFER_ADDR:
  697.       if (trans_control & TRANS_READY) /* Ignore if not ready */
  698.     {
  699.       trans_buffer = value & 0xff;
  700.       trans_control &= ~TRANS_READY;
  701.       trans_buffer_filled = TRANS_LATENCY;
  702.     }
  703.       break;
  704.  
  705.     case RECV_CTRL_ADDR:
  706.       recv_control = ((recv_control & ~RECV_INT_ENABLE)
  707.               | (value & RECV_INT_ENABLE));
  708.       break;
  709.  
  710.     case RECV_BUFFER_ADDR:
  711.       break;
  712.  
  713.     default:
  714.       run_error ("Write to unused memory-mapped IO address (0x%x)\n",
  715.          addr);
  716.     }
  717. }
  718.  
  719.  
  720. /* Invoked on a read in the memory-mapped IO area. */
  721.  
  722. #ifdef __STDC__
  723. static mem_word
  724. read_memory_mapped_IO (mem_addr addr)
  725. #else
  726. static mem_word
  727. read_memory_mapped_IO (addr)
  728.      mem_addr addr;
  729. #endif
  730. {
  731.   switch (addr)
  732.     {
  733.     case TRANS_CTRL_ADDR:
  734.       return (trans_control);
  735.  
  736.     case TRANS_BUFFER_ADDR:
  737.       return (trans_buffer & 0xff);
  738.  
  739.     case RECV_CTRL_ADDR:
  740.       return (recv_control);
  741.  
  742.     case RECV_BUFFER_ADDR:
  743.       recv_control &= ~RECV_READY;
  744.       recv_buffer_filled = 0;
  745.       return (recv_buffer & 0xff);
  746.  
  747.     default:
  748.       run_error ("Read from unused memory-mapped IO address (0x%x)\n",
  749.          addr);
  750.       return (0);
  751.     }
  752. }
  753.  
  754.  
  755.  
  756. /* Misc. routines */
  757.  
  758. #ifdef __STDC__
  759. void
  760. print_mem (mem_addr addr)
  761. #else
  762. void
  763. print_mem (addr)
  764.      mem_addr addr;
  765. #endif
  766. {
  767.   long value;
  768.  
  769.   if (TEXT_BOT <= addr && addr < text_top)
  770.     print_inst (addr);
  771.   else if (DATA_BOT <= addr && addr < data_top)
  772.     {
  773.       READ_MEM_WORD (value, addr);
  774.       write_output (message_out, "Data seg @ 0x%08x (%d) = 0x%08x (%d)\n",
  775.             addr, addr, value, value);
  776.     }
  777.   else if (stack_bot <= addr && addr < STACK_TOP)
  778.     {
  779.       READ_MEM_WORD (value, addr);
  780.       write_output (message_out, "Stack seg @ 0x%08x (%d) = 0x%08x (%d)\n",
  781.             addr, addr, value, value);
  782.     }
  783.   else if (K_TEXT_BOT <= addr && addr < k_text_top)
  784.     print_inst (addr);
  785.   else if (K_DATA_BOT <= addr && addr < k_data_top)
  786.     {
  787.       READ_MEM_WORD (value, addr);
  788.       write_output (message_out,
  789.             "Kernel Data seg @ 0x%08x (%d) = 0x%08x (%d)\n",
  790.             addr, addr, value, value);
  791.     }
  792.   else
  793.     error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr);
  794. }
  795.